

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.png">
  <link rel="icon" href="/img/favicon.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="Cheney">
  <meta name="keywords" content="Coding">
  
    <meta name="description" content="RSA公开密钥密码体制是一种使用不同的加密密钥与解密密钥，“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制 。程序实现了公钥和私钥的获取，以及进一步的利用公钥和私钥进行加解密。">
<meta property="og:type" content="article">
<meta property="og:title" content="RSA原理与实现">
<meta property="og:url" content="https://cheney822.gitee.io/2022/04/05/rsa/index.html">
<meta property="og:site_name" content="Cheney blog">
<meta property="og:description" content="RSA公开密钥密码体制是一种使用不同的加密密钥与解密密钥，“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制 。程序实现了公钥和私钥的获取，以及进一步的利用公钥和私钥进行加解密。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://imgbed.cheney.cc/picgo/image-20220406001245868.png">
<meta property="og:image" content="https://imgbed.cheney.cc/picgo/image-20220406001339131.png">
<meta property="og:image" content="https://imgbed.cheney.cc/picgo/wps9olRHK.jpg">
<meta property="og:image" content="https://imgbed.cheney.cc/picgo/wps46PnMR.jpg">
<meta property="og:image" content="https://imgbed.cheney.cc/picgo/wpsvVeGw1.jpg">
<meta property="og:image" content="https://imgbed.cheney.cc/picgo/wpsVKBL0y.jpg">
<meta property="og:image" content="https://imgbed.cheney.cc/picgo/wpsD9quFQ.jpg">
<meta property="og:image" content="https://imgbed.cheney.cc/picgo/wpspP7oTq.jpg">
<meta property="og:image" content="https://imgbed.cheney.cc/picgo/wpsYiELg4.jpg">
<meta property="og:image" content="https://imgbed.cheney.cc/picgo/wpsTUh9Yg.jpg">
<meta property="og:image" content="https://imgbed.cheney.cc/picgo/wpsPLdgpD.jpg">
<meta property="og:image" content="https://imgbed.cheney.cc/picgo/wps37E7M4.jpg">
<meta property="og:image" content="https://imgbed.cheney.cc/picgo/wps7F9HNn.jpg">
<meta property="og:image" content="https://imgbed.cheney.cc/picgo/wpsn5QRec.jpg">
<meta property="og:image" content="https://imgbed.cheney.cc/picgo/wpsmOcrdL.jpg">
<meta property="article:published_time" content="2022-04-05T15:00:00.000Z">
<meta property="article:modified_time" content="2022-04-05T16:36:35.274Z">
<meta property="article:author" content="Cheney">
<meta property="article:tag" content="Python">
<meta property="article:tag" content="加密">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://imgbed.cheney.cc/picgo/image-20220406001245868.png">
  
  
  <title>RSA原理与实现 - Cheney blog</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4/github-markdown.min.css" />
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hint.css@2/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@10/styles/github-gist.min.css" />
    
  

  
    <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.css" />
  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    var CONFIG = {"hostname":"cheney822.gitee.io","root":"/","version":"1.8.14","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"copy_btn":true,"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":1},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/local-search.xml"};
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.4.1"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>Cheney Blog</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              &nbsp;<i class="iconfont icon-search"></i>&nbsp;
            </a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner" id="banner" parallax=true
         style="background: url('https://imgbed.cheney.cc/Blog_config/default.png') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="page-header text-center fade-in-up">
            <span class="h2" id="subtitle" title="RSA原理与实现">
              
            </span>

            
              <div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2022-04-05 23:00" pubdate>
        2022年4月5日 晚上
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      3.2k 字
    </span>
  

  
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      17 分钟
    </span>
  

  
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">RSA原理与实现</h1>
            
            <div class="markdown-body">
              <blockquote>
<p>源码：<a target="_blank" rel="noopener" href="https://gitee.com/Cheney822/programmes/blob/master/rsa.py">https://gitee.com/Cheney822/programmes/blob/master/rsa.py</a></p>
</blockquote>
<h1 id="1背景"><a href="#1背景" class="headerlink" title="1背景"></a>1背景</h1><h2 id="1-1-数据加密"><a href="#1-1-数据加密" class="headerlink" title="1.1 数据加密"></a>1.1 数据加密</h2><p>指的是根据一定规则，将数据处理成不规则的数据，使得人们除非有了关键的钥匙以及得知这个规则，难于得知无规则数据的真实含义。这个一定规则 就是加密算法，这个钥匙就是密钥。</p>
<p>数据加密分为对称密钥加密以及非对称密钥加密：</p>
<ul>
<li>对称密钥加密： 双方共同持有这个密钥，发送方用这个密钥按照指定的算法将数据加密，再发出去；接收方用这个密钥将接收到的数据解密，以得到真实的数据含义。由于双方都持有这个密钥，而且内容相同，所以叫对称密钥</li>
<li>非对称密钥加密：这种加密方式的密钥是一对，发送方用其中的一把钥匙将数据加密，再发出去；接收方用这对密钥的另一把钥匙将数据解密，以得到真实的数据含义。发送方持有密钥中的一把钥匙，接收方持有另外一把。接收方持有的钥匙叫 私钥, 而接收方持有的这把钥匙叫公钥 。两把钥匙不一样，所以叫做非对称密钥加密，也叫做公开密钥算法。</li>
</ul>
<h2 id="1-2-非对称密钥加密"><a href="#1-2-非对称密钥加密" class="headerlink" title="1.2 非对称密钥加密"></a>1.2 非对称密钥加密</h2><p>RSA公开密钥密码体制是一种使用不同的加密密钥与解密密钥，“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制 。<br>在公开密钥密码体制中，加密密钥（即公开密钥）PK是公开信息，而解密密钥（即秘密密钥）SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的，但却不能根据PK计算出SK 。<br>正是基于这种理论，1978年出现了著名的RSA算法，它通常是先生成一对RSA密钥，其中之一是保密密钥，由用户保存；另一个为公开密钥，可对外公开，甚至可在网络服务器中注册。为提高保密强度，RSA密钥至少为500位长，一般</p>
<p>推荐使用1024位。这就使加密的计算量很大。为减少计算量，在传送信息时，常采用传统加密方法与公开密钥加密方法相结合的方式，即信息采用改进的DES或IDEA对话密钥加密，然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后，用不同的密钥解密并可核对信息摘要。<br>RSA是被研究得最广泛的公钥算法，从提出到现在已近三十年，经历了各种攻击的考验，逐渐为人们接受，普遍认为是目前最优秀的公钥方案之一。</p>
<p>RSA公开密钥密码体制的原理是：根据数论，寻求两个大素数比较简单，而将它们的乘积进行因式分解却极其困难，因此可以将乘积公开作为加密密钥.</p>
<h1 id="2概要设计"><a href="#2概要设计" class="headerlink" title="2概要设计"></a>2概要设计</h1><h2 id="2-1-函数"><a href="#2-1-函数" class="headerlink" title="2.1 函数"></a>2.1 函数</h2><p>程序涉及到的函数及功能如下：</p>
<img src="https://imgbed.cheney.cc/picgo/image-20220406001245868.png" srcset="/img/loading.gif" lazyload alt="image-20220406001245868" style="zoom:50%;" />



<h2 id="2-2-接口"><a href="#2-2-接口" class="headerlink" title="2.2 接口"></a>2.2 接口</h2><p>程序文件对外开放的方法有三个，分别是加解密和获取密钥。</p>
<ul>
<li>首先是获取密钥newkeys函数，该函数获取一个参数nbits用来指定密钥的位数。函数返回两个list，每个list内有两个元素，分别为[N, e], [N, d]。</li>
<li>然后是加密函数，该函数接受两个参数，分别为：待加密的明文和公钥。待加密的信息为Bytes类型，公钥为[int, int]类型，返回值为一个list，其中的每一项分别对应bytes的每一位。</li>
<li>最后是解密函数，该函数与加密函数类似。不同之处在于其接受的密文是list类型（对应加密的返回值），返回的是bytes类型（对应用户输入系统的数据类型）<br>加解密过程中数据的变化如下图所示：</li>
</ul>
<img src="https://imgbed.cheney.cc/picgo/image-20220406001339131.png" srcset="/img/loading.gif" lazyload alt="image-20220406001339131" style="zoom:50%;" />

<p>以上对外的接口内部会调用内部函数（以__开头），外部在使用时不建议直接调用。</p>
<h2 id="2-3-流程"><a href="#2-3-流程" class="headerlink" title="2.3 流程"></a>2.3 流程</h2><p>RSA算法的具体描述如下：</p>
<p>（1）任意选取两个不同的大素数p和q计算乘积<br><img src="https://imgbed.cheney.cc/picgo/wps9olRHK.jpg" srcset="/img/loading.gif" lazyload alt="img" style="zoom: 10%;" /> </p>
<p>（2）任意选取一个大整数e，满足<br><img src="https://imgbed.cheney.cc/picgo/wps46PnMR.jpg" srcset="/img/loading.gif" lazyload alt="img" style="zoom:10%;" /> |</p>
<p>整数e用做加密钥（注意：e的选取是很容易的，例如，所有大于p和q的素数都可用）</p>
<p>（3）确定的解密钥d，满足</p>
<img src="https://imgbed.cheney.cc/picgo/wpsvVeGw1.jpg" srcset="/img/loading.gif" lazyload alt="img" style="zoom:10%;" /> 

<p> 即</p>
<img src="https://imgbed.cheney.cc/picgo/wpsVKBL0y.jpg" srcset="/img/loading.gif" lazyload alt="img" style="zoom:10%;" /> 

<p> 是一个任意的整数；所以，若知道e和 <img src="https://imgbed.cheney.cc/picgo/wpsD9quFQ.jpg" srcset="/img/loading.gif" lazyload alt="img" style="zoom:2%;" />，则很容易计算出d ；</p>
<p>（4）公开整数n和e，秘密保存d ；</p>
<p>（5）将明文m（m&lt;n是一个整数）加密成密文c，加密算法为<br><img src="https://imgbed.cheney.cc/picgo/wpspP7oTq.jpg" srcset="/img/loading.gif" lazyload alt="img" style="zoom:10%;" /> |</p>
<p>（6）将密文c解密为明文m，解密算法为:</p>
<img src="https://imgbed.cheney.cc/picgo/wpsYiELg4.jpg" srcset="/img/loading.gif" lazyload alt="img" style="zoom:10%;" /> 

<p>然而只根据n和e（注意：不是p和q）要计算出d是不可能的。因此，任何人都可对明文进行加密，但只有授权用户（知道d）才可对密文解密</p>
<h1 id="3详细设计"><a href="#3详细设计" class="headerlink" title="3详细设计"></a>3详细设计</h1><h2 id="生成密钥"><a href="#生成密钥" class="headerlink" title="生成密钥"></a>生成密钥</h2><ul>
<li>第一步，随机选择两个不相等的质数p和q。</li>
<li>第二步，计算p和q的乘积n。</li>
<li>第三步，计算n的欧拉函数φ(n)。φ(n) = (p-1)(q-1)</li>
<li>第四步，随机选择一个整数e，条件是1&lt; e &lt; φ(n)，且e与φ(n) 互质。</li>
<li>第五步，计算e对于φ(n)的模反元素d。所谓”模反元素”就是指有一个整数d，可以使得ed被φ(n)除的余数为1。</li>
<li>第六步，将n和e封装成公钥，n和d封装成私钥。</li>
</ul>
<img src="https://imgbed.cheney.cc/picgo/wpsTUh9Yg.jpg" srcset="/img/loading.gif" lazyload alt="img" style="zoom: 50%;" /> 

<h2 id="3优化的判断素数方法"><a href="#3优化的判断素数方法" class="headerlink" title="3优化的判断素数方法"></a>3优化的判断素数方法</h2><h3 id="主要优化的规则"><a href="#主要优化的规则" class="headerlink" title="主要优化的规则"></a>主要优化的规则</h3><ul>
<li>1.大于3的素数一定在6的倍数前一个或后一个（如素数37在36的后面）</li>
<li>2.要判断n是否为素数，只需要让n从2开始，依次除到根号n即可</li>
<li>3.在进行“让n从2开始，依次除到根号n”过程中，若n除以2的余数不为0，可以直接跳过[2, sqrt(n)]里面的所有偶数</li>
</ul>
<h3 id="复杂度分析"><a href="#复杂度分析" class="headerlink" title="复杂度分析"></a>复杂度分析</h3><p>1.最基础的算法：也就是让n从2开始判断，一直到n-1<br>    若遇到的数是素数时，此时需要进行n-2次判断<br>    当遇到的不是素数时，要进行a（2&lt;a&lt;n-2)次判断<br>    也就是说时间复杂度为n</p>
<p>2.改进后的算法：<br>    根据规则二，判断素数只要从[2，sqrt(n)]即可，此时复杂度为sqrt(n)<br>    根据规则3，无论如何都可以不判断2之后的偶数（当n大于2，当n除尽2时，n不为素数，之后不需要判断，如果n除不尽2时，之后的偶数不要判断）<br>    假设n可以除尽2和不可以除尽2概率相等，那此时复杂度为sqrt(n)/4<br>    根据规则一，只有1/3的数要进行判断，此时复杂度为sqrt(n)/12<br>    也就是说时间复杂度为sqrt(n)/12</p>
<h2 id="快速幂取模运算"><a href="#快速幂取模运算" class="headerlink" title="快速幂取模运算"></a>快速幂取模运算</h2><p>输入x,n,p，如何计算xn mod p？</p>
<p>  暴力的做法就是直接将n个x乘起来，最终mod p。理论上来说，这样做显然是可以的，但是很明显，这样做的话，程序要循环n次，也就是说它的时间复杂度是O(n)，如果n非常大，算法的效率就特别低，为此引入列快速幂运算。</p>
<p>  快速幂的本质就是：底数不断取2次幂，指数不断除2次幂，直到指数除到为1，计算完毕。原先的n次幂运算，它的时间复杂度为O(n)，而如果是快速幂运算，时间复杂度就被降到了O(log2n)。</p>
<p>但是，这个过程中，如果指数的奇数的话，就没有办法除2次幂。对于整数的除，都是整除。例如求2的5次方，经过一次快速幂，它并不会变成4的2.5次方，而是4的2次方，因为4整除2等于2。跟实际还是差了一个4的0.5次方，也就是“原底数”。</p>
<p>  每一次到奇数幂时，就会有这些原底数被漏乘，最终形成一群因为是奇数幂而漏乘的“底数群”。因此，我们需要对奇数次幂的情况进行特判，存储这些没乘上的底数群，最终return的时候将它们都乘上。</p>
<p>  由上，引入一个每一次处理奇数次幂时，未被底数乘上的待乘底数群。这个底数群的初始值为1，当为奇数次幂时，这个未乘的底数群就以乘以目前的底数的形式进行更新。最后，这个未乘的底数群乘幂为1时不包含奇数幂时遗漏的底数的不完全结果，就是快速幂的最终结果。</p>
<p>  然后再加入取模操作即可。</p>
<h2 id="扩展欧几里得算法"><a href="#扩展欧几里得算法" class="headerlink" title="扩展欧几里得算法"></a>扩展欧几里得算法</h2><p>​    欧几里得算法是求最大公约数的算法, 也就是辗转相除法。记 gcd(a,b) 为a和b的最大公约数，欧几里得算法的基本原理是gcd(a,b)==gcd(b,a%b),(b!=0) 和 gcd(a,0)==a 。</p>
<p>应用在RSA加密算法求逆元中：</p>
<p>​    首先我们知道，再求两个数的最大公约数的时候可以用欧几里得算法。在欧几里得算法中，通过辗转相除，当余数为0的时候最后的除数就是两个数的最大公约数。</p>
<p>​    而在其扩展算法中，我们已知两个数的最大公约数，我们已知 ax = 1(mod p),展开就是 ax mod p = 1，首先我们先求 p = x1 * a + p1，然后p = a，a = p1，迭代下去</p>
<p>​    知道pi = 1（i表示出了i次）为之，然后就可以得出 1 = p - xi * a，此时的a和p已经不是我们初始的a和p了，我们需要往前推，推到 1= yp + x*a 为止，此时得出的x就是a的逆元。</p>
<p>​    如果逆元x为负数，或者比p大，要对其就行取余操作。</p>
<h1 id="4运行测试"><a href="#4运行测试" class="headerlink" title="4运行测试"></a>4运行测试</h1><h2 id="4-1获取密钥"><a href="#4-1获取密钥" class="headerlink" title="4.1获取密钥"></a>4.1获取密钥</h2><img src="https://imgbed.cheney.cc/picgo/wpsPLdgpD.jpg" srcset="/img/loading.gif" lazyload alt="img" style="zoom:50%;" /> 

<h2 id="4-2加密"><a href="#4-2加密" class="headerlink" title="4.2加密"></a>4.2加密</h2><img src="https://imgbed.cheney.cc/picgo/wps37E7M4.jpg" srcset="/img/loading.gif" lazyload alt="img" style="zoom:50%;" /> 


<h2 id="4-3解密"><a href="#4-3解密" class="headerlink" title="4.3解密"></a>4.3解密</h2><img src="https://imgbed.cheney.cc/picgo/wps7F9HNn.jpg" srcset="/img/loading.gif" lazyload alt="img" style="zoom:50%;" /> 

<h2 id="4-4完整操作"><a href="#4-4完整操作" class="headerlink" title="4.4完整操作"></a>4.4完整操作</h2><img src="https://imgbed.cheney.cc/picgo/wpsn5QRec.jpg" srcset="/img/loading.gif" lazyload alt="img" style="zoom: 50%;" /> 

<p>结果：<img src="https://imgbed.cheney.cc/picgo/wpsmOcrdL.jpg" srcset="/img/loading.gif" lazyload alt="img" style="zoom: 50%;" /> </p>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/">数据库</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/Python/">Python</a>
                    
                      <a class="hover-with-bg" href="/tags/%E5%8A%A0%E5%AF%86/">加密</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">
                  
                    本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！
                  
                </p>
              
              
                <div class="post-prevnext">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2022/04/24/gitignore/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">gitignore简单入门教程</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2022/03/23/Des%E5%8A%A0%E5%AF%86/">
                        <span class="hidden-mobile">Des加密</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
    

    
  </main>

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://cheney822.gitee.io/" target="_blank" rel="nofollow noopener"><span>备用网址</span></a> 
  </div>
  

  
  <!-- 备案信息 -->
  <div class="beian">
    <span>
      <a href="http://beian.miit.gov.cn/" target="_blank" rel="nofollow noopener">
        皖ICP备2022002876号-1
      </a>
    </span>
    
  </div>


  
</footer>


  <!-- SCRIPTS -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>

<!-- Plugins -->


  <script  src="/js/local-search.js" ></script>



  
    <script  src="/js/img-lazyload.js" ></script>
  



  



  
    <script  src="https://cdn.jsdelivr.net/npm/tocbot@4/dist/tocbot.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/anchor-js@4/anchor.min.js" ></script>
  
  
    <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js" ></script>
  






  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var title = document.getElementById('subtitle').title;
      
        typing(title);
      
    })(window, document);
  </script>















<!-- 主题的启动项 保持在最底部 -->
<script  src="/js/boot.js" ></script>


</body>
</html>
